#!/usr/bin/python
# -*- coding: utf-8 -*-
# Created on 2017-02-14 上午10:27
# @auther: chenyongbing
# @file: views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponseRedirect
# Create your views here.

from django.core.cache import caches
from django.conf import settings
from .models import *

from django_redis import get_redis_connection
# conn = get_redis_connection("default")
import re , os , json



class RedisChannel():
    def __init__(self,env_name):
        self.conn = get_redis_connection(env_name)
        self.env_name = env_name
        self.base_key = "/{env}/{group}/{project}/{status}"


    def copy( self,pipe, src, dest):
        for key in self.conn.keys(src + '/*'):
            value = self.conn.get(key)
            nkey = re.sub(src, dest, key.decode("utf-8"))
            pipe.set(nkey, value)


    def exists(self, key):
        if not self.conn.keys(key + '/*'):
            print("Redis key [{key}] not exists.".format(key=key))
            return False
        else:
            return True


    def delete_dir(self, pipe, src):
        if self.conn.exists(src):
            pipe.delete(src)
            return
        for key in self.conn.keys(src + '/*'):
            pipe.delete(key)




    def get_service_pipeline_count(self,group,project,status):
        search_key = self.base_key.format(env=self.env_name,group=group,project=project,status=status) +'/*'
        keys = self.conn.keys(search_key)
        values = []
        for key in keys:
            key = key.decode('utf-8')
            # return key.decode("utf-8").split('/')[5]
            value = self.conn.get(key).decode("utf-8")
            print(key,value)
            values.append('{key} : {value}'.format(key='/'.join(key.split('/')[5:]),value=value))
        return '<br/>'.join(values)

    def online_action_all(self,datas):
        pipe = self.conn.pipeline()
        status = True
        for data in datas:
            group = data.get('group', None)
            project = data.get('project', None)
            if not self.online_action(pipe, group=group, project=project):
                status = False
                break
        if status:
            pipe.execute()
            return True
        else:
            pipe.reset()
            return False

    def online_action(self,pipe,group=None, project=None):
        waiting_key = self.base_key.format(env=self.env_name,group=group,project=project,status='waiting')
        online_key = self.base_key.format(env=self.env_name,group=group,project=project,status='online')
        offline_key = self.base_key.format(env=self.env_name,group=group,project=project,status='offline')
        invalid_key = self.base_key.format(env=self.env_name,group=group,project=project,status='invalid')

        if not self.exists(waiting_key): return False

        # delete invalid key
        # delete_dir(pipe,invalid_key)
        # copy offline key to invalid key
        self.copy(pipe, offline_key, invalid_key)
        # delete offline key
        self.delete_dir(pipe, offline_key)
        # copy online key to offline key
        self.copy(pipe, online_key, offline_key)
        # delete online key
        self.delete_dir(pipe, online_key)
        # copy waiting key to online key
        self.copy(pipe, waiting_key, online_key)
        # del waiting key
        self.delete_dir(pipe, waiting_key)

        return True

    def goback_action_all(self,datas):
        pipe = self.conn.pipeline()
        status = True
        for data in datas:
            group = data.get('group', None)
            project = data.get('project', None)
            if not self.goback_action(pipe, group=group, project=project):
                status = False
                break
        if status:
            pipe.execute()
            return True
        else:
            pipe.reset()
            return False

    def goback_action(self,pipe, group=None, project=None):
        waiting_key = self.base_key.format(env=self.env_name, group=group, project=project, status='waiting')
        online_key = self.base_key.format(env=self.env_name, group=group, project=project, status='online')
        offline_key = self.base_key.format(env=self.env_name, group=group, project=project, status='offline')
        invalid_key = self.base_key.format(env=self.env_name, group=group, project=project, status='invalid')
        if not self.exists(offline_key): return False

        # delete waiting key
        # cli.del_key(waiting_key)
        # copy online to waiting ;
        # cli.copy(online_key , waiting_key)
        # delete online key
        self.delete_dir(pipe, online_key)
        # copy offline key to online
        self.copy(pipe, offline_key, online_key)
        # delete offline key
        self.delete_dir(pipe, offline_key)
        # copy invalid key to offline
        # cli.copy(invalid_key , offline_key)

        return True





def envView(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/account/login')
    # datas = list(Env.objects.all().values())
    # return render(request, 'envs.html', {"body_title":"环境列表","datas":datas})


def _get_env_name(request):
    url_path = request.path
    if len(url_path)>=3:
        return url_path.split('/')[2]
    else:
        return None



def cutover_perm(view):
    def decorator(request, *args, **kwargs):
        if not request.user.is_authenticated():
            if request.method=='GET':
                return HttpResponseRedirect('/account/login')
            elif request.method == 'POST':
                return HttpResponse(json.dumps({'code':10010,'msg':'未登陆'}))
        if not request.user.has_perm('cutover.cutover_admin'):
            if request.method=='GET':
                return render(request, 'templates/403.html')
            elif request.method == 'POST':
                return HttpResponse(json.dumps({'code':10011,'msg':'无权限'}))
        return view(request, *args, **kwargs)

    return decorator

@csrf_exempt
@cutover_perm
def services_view(request):
    print(list(dict(settings.CACHES).keys()))
    # print(dict(settings.CACHES).has_key("DD"))
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/account/login')
    env_name = _get_env_name(request)
    if env_name not in list(dict(settings.CACHES).keys()):return render(request,'templates/404.html')
    if request.method=='GET':
        return render(request, 'cutover/templates/services.html',{})
    elif request.method=='POST':
        datas = Service.objects.all()
        myRedisChannel = RedisChannel(env_name)
        newdatas = []
        for data in datas:
            id = data.id
            # env = data.env
            group = data.group.name
            project = data.name
            waiting_pipeline_count = myRedisChannel.get_service_pipeline_count(group = group , project=project , status = 'waiting')
            online_pipeline_count = myRedisChannel.get_service_pipeline_count(group = group , project=project , status = 'online')
            offline_pipeline_count = myRedisChannel.get_service_pipeline_count(group = group , project=project , status = 'offline')

            newdatas.append({'id':id,'env':env_name,'group':group,'project':project,
                             'waiting':waiting_pipeline_count,
                             'online':online_pipeline_count,
                             'offline':offline_pipeline_count})
        return HttpResponse(json.dumps(newdatas))










@csrf_exempt
@cutover_perm
def online(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/account/login')

    if request.method=='POST':

        strJson = request.POST.get('strJson',[])
        if strJson==[] or strJson == "":
            return HttpResponse(json.dumps({'code': 10002, 'msg': '上线失败,请求数据缺失.'}))
        if isinstance(strJson , str):
            datas = json.loads(strJson)
        if isinstance(datas , dict):
            datas = [datas]
        print(datas)
        if len(datas)==0:
            return HttpResponse(json.dumps({'code': 10002, 'msg': '上线失败,请求数据缺失.'}))
        env_name = datas[0].get('env',None)
        if env_name == None:
            return HttpResponse(json.dumps({'code': 10002, 'msg': '上线失败,请求数据缺失.'}))

        if env_name not in list(dict(settings.CACHES).keys()):
            return HttpResponse(json.dumps({'code': 10003, 'msg': '上线失败,redis配置确实.'}))

        myRedisChannel = RedisChannel(env_name)
        if myRedisChannel.online_action_all(datas):
            return HttpResponse(json.dumps({'code':10000,'msg':'上线成功.'}))
        else:
            return HttpResponse(json.dumps({'code': 10001, 'msg': '上线失败,waiting Key不存在.'}))
@csrf_exempt
@cutover_perm
def goback(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/account/login')
    # env_name = _get_env_name(request)
    # if env_name not in list(dict(settings.CACHES).keys()): return render(request, 'templates/404.html')
    if request.method=='POST':
        # myRedisChannel = RedisChannel(env_name)
        strJson = request.POST.get('strJson',[])
        if strJson==[] or strJson == "":
            return HttpResponse("无设置项")
        if isinstance(strJson , str):
            datas = json.loads(strJson)
        if isinstance(datas , dict):
            datas = [datas]
        if len(datas)==0:
            return HttpResponse(json.dumps({'code': 10002, 'msg': '上线失败,请求数据缺失.'}))
        env_name = datas[0].get('env',None)
        if env_name == None:
            return HttpResponse(json.dumps({'code': 10002, 'msg': '上线失败,请求数据缺失.'}))

        if env_name not in list(dict(settings.CACHES).keys()):
            return HttpResponse(json.dumps({'code': 10003, 'msg': '上线失败,redis配置确实.'}))

        myRedisChannel = RedisChannel(env_name)
        if myRedisChannel.goback_action_all(datas):

            return HttpResponse(json.dumps({'code': 10000, 'msg': '回退成功.'}))
        else:
            return HttpResponse(json.dumps({'code': 10001, 'msg': '回退失败,确认存在offline Key.'}))